//
//  NSObject+localDataBaseCache.m
//  webViewLocal
//
//  Created by wjc on 2021/12/3.
//

#import "NSObject+localDataBaseCache.h"
#import "NSObject+FCUrlPathGet.h"
#import "dataBaseTool.h"
#import "NSDictionary+setDic.h"
@implementation NSObject (localDataBaseCache)
/// 获取对象属性
/// @param saveClass 对象
/// @param re 是否返回属性类型是为返回属性类型,否为是返回属性名称
/// re为true,返回结构类型名称
/// re为false,返回结构字段名称
-(NSMutableArray*)getAllPropertNameWithClass:(Class)saveClass returnClass:(BOOL)re{
    unsigned int outCount, i;
        // 获取对象里的属性列表
    objc_property_t * properties = class_copyPropertyList(saveClass , &outCount);
    NSMutableArray *arr = [NSMutableArray new];
    for (i = 0; i < outCount; i++) {
        
        objc_property_t property =properties[i];
            //  属性名转成字符串
        NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        const char *objName = [NSObject getControllerIvalWithController:saveClass andPropertyName:propertyName];
        NSString *objNameStr=[NSString stringWithFormat:@"%s",objName];

        if (re) {
            [arr addObject:objNameStr];
        }else{
            [arr addObject:propertyName];
        }
    }
    free(properties);
    return arr;
}

/// 建表
- (void)createNewDataBaseWithTableView{
    if (self.mjClass) {
    [dataBaseTool setDataBaseWithSQLTxt:^NSString *{
        NSArray *property = [self getAllPropertNameWithClass:[self.mjClass class] returnClass:NO];
        NSArray *propertyClass = [self getAllPropertNameWithClass:[self.mjClass class] returnClass:YES];
        NSMutableArray *arr = [NSMutableArray new];
        for (int i = 0; i <propertyClass.count; i++) {
            NSString *propertyName = property[i];
            NSString *type = propertyClass[i];
         if (type.length==1||[type isEqual:@"NSMutableString"]||[type isEqual:@"NSString"]||[type isEqual:@"NSNumber"]) {///数字类型,布尔类型,字符串,等主类型,直接加入
                        [arr addObject:propertyName];
                    }else if([type isEqual:@"NSDictionary"]
                             ||[type isEqual:@"NSMutableDictionary"]
                             ){///字典类型(说明位转成模型),直接加入
                        [arr addObject:propertyName];
                    }else if([type isEqual:@"NSMutableArray"]||[type isEqual:@"NSArray"]){
                        ///字典类型(说明位转成模型),需要判断是否有转化成模型的方法,如果有,直接跳过,如果没有,添加字段
                                           if ([[self.mjClass class] respondsToSelector:NSSelectorFromString(@"mj_objectClassInArray")]) {
                                               if ([[self.mjClass class] mj_objectClassInArray][property[i]]) {
                                                   Class cls =[[[self.mjClass class] mj_objectClassInArray][property[i]] isKindOfClass:[NSString class]]?NSClassFromString([[self.mjClass class] mj_objectClassInArray][property[i]]):[[self.mjClass class] mj_objectClassInArray][property[i]];
                                                   NSObject* obj =[[cls alloc] init];
                                                   obj.mjClass =[[cls alloc] init];
                                                   [obj createNewDataBaseWithTableView];
                                               }
                                               
                                            }else{
                                                [arr addObject:propertyName];
                                            }
                        
                    }else{
                        ///排除所有字段,就剩下模型字段,返回再建表
                        NSObject* obj =[[NSClassFromString(type) alloc] init];
                        obj.mjClass =[[NSClassFromString(type) alloc] init];
                        [obj createNewDataBaseWithTableView];
                    }
        }
            
        if (arr.count>0) {
            NSMutableString *str=[NSMutableString new];
            [str appendFormat:@"create table if not exists %@ (",NSStringFromClass([self.mjClass class])];
            for (NSString *columnName in arr) {
                [str appendFormat:@"%@ text NULL DEFAULT '',",columnName];
            }
            str =[[str substringToIndex:str.length -1] mutableCopy];
            [str appendString:@",[countId] integer PRIMARY KEY autoincrement,[meId] text NULL DEFAULT '')"];
            return str;
        }
        return nil;
    } andFail:^(NSString * _Nonnull errorDes) {
        WJCLog(@"💔💔创建数据库报错:%@💔💔",errorDes);
    }];
    }
}
-(NSString*)getKVTypeValueWithProperty:(NSString*)propertyName{
    NSArray *property = [self getAllPropertNameWithClass:[self.mjClass class] returnClass:NO];
    NSArray *propertyClass = [self getAllPropertNameWithClass:[self.mjClass class] returnClass:YES];
    for (int i = 0; i <property.count; i++) {
        if ([propertyName isEqual:property[i]]) {
            return propertyClass[i];
        }
    }
    return nil;
}
///增
- (void)insertNewDataBaseWithDic:(NSDictionary *)content{
    if (self.mjClass) {
        if (content.count>0) {
        NSMutableArray *titleArr = [NSMutableArray new];///表标签
            NSMutableArray *contentArr = [NSMutableArray new];///表内容
            for (NSString *key in content) {
                if(!content[key]){
                    continue;
                }
                
                NSDictionary *replace = [[self.mjClass class] respondsToSelector:@selector(wjc_localDataBaseUnion)]?[[self.mjClass class] wjc_localDataBaseUnion]:@{};
                NSArray *arr = [replace[key] componentsSeparatedByString:@"."];
                if ([content[key] isKindOfClass:[NSDictionary class]]) {
                    NSString *className = [self getKVTypeValueWithProperty:key];
                    if(className.length>1&&![className isEqual:@"NSMutableString"]&&![className isEqual:@"NSString"]&&![className isEqual:@"NSNumber"]&&![className isEqual:@"NSDictionary"]
                           &&![className isEqual:@"NSMutableDictionary"]){
                        
                        if (arr.count>0) {
                            Class cls =[[[self.mjClass class] mj_objectClassInArray][key] isKindOfClass:[NSString class]]?NSClassFromString([[self.mjClass class] mj_objectClassInArray][key]):[[self.mjClass class] mj_objectClassInArray][key];
                            NSObject* obj =[[cls alloc] init];
                            obj.mjClass =[[cls alloc] init];
                            [obj updateNewDataBaseWithDic:content[key] andLimitType:@{arr.lastObject:[content valueForKey:key]}];
                        }else{
                           
                            NSString *typeStr,*typeKey;
                            for (NSString* k in replace) {
                                arr =[replace[k] componentsSeparatedByString:@"."];
                                typeStr = [content valueForKey:k];
                                typeKey = arr.lastObject;
                                
                            }
                            NSObject* obj =[[NSClassFromString(className) alloc] init];
                            obj.mjClass =[[NSClassFromString(className) alloc] init];
                            [obj updateNewDataBaseWithDic:content[key] andLimitType:@{typeKey:typeStr}];
                        }
                        
                    }
                }else if ([content[key] isKindOfClass:[NSArray class]]) {
                    if ([[self.mjClass class] respondsToSelector:NSSelectorFromString(@"mj_objectClassInArray")]) {
                        if ([[self.mjClass class] mj_objectClassInArray][key]&&arr.count>0) {
                            Class cls =[[[self.mjClass class] mj_objectClassInArray][key] isKindOfClass:[NSString class]]?NSClassFromString([[self.mjClass class] mj_objectClassInArray][key]):[[self.mjClass class] mj_objectClassInArray][key];
                            NSObject* obj =[[cls alloc] init];
                            obj.mjClass =[[cls alloc] init];
                            for (NSDictionary *d in content[key]) {
                                [obj updateNewDataBaseWithDic:d andLimitType:@{arr.lastObject:[content valueForKey:key]}];
                            }
                            
                        }
                }
                }else{
                [titleArr addObject:[NSString stringWithFormat:@"[%@]",key]];
                [contentArr addObject:[NSString stringWithFormat:@"'%@'",content[key]]];
                }
            }
            [dataBaseTool setDataBaseWithSQLTxt:^NSString *{
            if (titleArr.count>0&&titleArr.count == contentArr.count) {
                NSString *updateCode=[NSString stringWithFormat:@"insert into %@ (%@) values (%@)",  NSStringFromClass([self.mjClass class]),[titleArr componentsJoinedByString:@","],[contentArr componentsJoinedByString:@","]];
                return updateCode;
            }
            return nil;
        } andFail:^(NSString * _Nonnull errorDes) {
            WJCLog(@"💔💔数据库插入数据报错:%@💔💔",errorDes);
                if ([errorDes containsString:@"no such table"]) {
                    [self createNewDataBaseWithTableView];
                   
                }
        }];
        }
            
    }
    
}

-(void)updateNewDataBaseWithDic:(NSDictionary*)content andLimitType:(NSDictionary *)type{
    if ([content isKindOfClass:[NSDictionary class]]) {
    [self getNewDataBaseWithLimitType:type andGetSub:NO andOnlyValue:NO andsuccess:^(NSArray * _Nonnull obj) {
        if (obj.count>0) {
            if (content.count>0) {
                NSMutableArray *contentArr = [NSMutableArray new];///表内容
                for (NSString *key in content) {
                    if(!content[key]){
                        continue;
                    }
                    NSDictionary *replace = [[self.mjClass class] wjc_localDataBaseUnion];
                    NSArray *arr = [replace[key] componentsSeparatedByString:@"."];
                    if ([content[key] isKindOfClass:[NSDictionary class]]) {
                        NSString *className = [self getKVTypeValueWithProperty:key];
                        if(className.length>1&&![className isEqual:@"NSMutableString"]&&![className isEqual:@"NSString"]&&![className isEqual:@"NSNumber"]&&![className isEqual:@"NSDictionary"]
                               &&![className isEqual:@"NSMutableDictionary"]){
                            
                            if (arr.count>0) {
                                Class cls =[[[self.mjClass class] mj_objectClassInArray][key] isKindOfClass:[NSString class]]?NSClassFromString([[self.mjClass class] mj_objectClassInArray][key]):[[self.mjClass class] mj_objectClassInArray][key];
                                NSObject* obj =[[cls alloc] init];
                                obj.mjClass =[[cls alloc] init];
                                [obj updateNewDataBaseWithDic:content[key] andLimitType:@{arr.lastObject:[content valueForKey:key]}];
                            }else{
                                
                                NSString *typeStr,*typeKey;
                                for (NSString* k in replace) {
                                    arr =[replace[k] componentsSeparatedByString:@"."];
                                    typeStr = [content valueForKey:k];
                                    typeKey = arr.lastObject;
                                    
                                }
                                NSObject* obj =[[NSClassFromString(className) alloc] init];
                                obj.mjClass =[[NSClassFromString(className) alloc] init];
                                [obj updateNewDataBaseWithDic:content[key] andLimitType:@{typeKey:typeStr}];
                            }
                            
                        }
                    }else if ([content[key] isKindOfClass:[NSArray class]]) {
                        if ([[self.mjClass class] respondsToSelector:NSSelectorFromString(@"mj_objectClassInArray")]) {
                            if ([[self.mjClass class] mj_objectClassInArray][key]&&arr.count>0) {
                                Class cls =[[[self.mjClass class] mj_objectClassInArray][key] isKindOfClass:[NSString class]]?NSClassFromString([[self.mjClass class] mj_objectClassInArray][key]):[[self.mjClass class] mj_objectClassInArray][key];
                                NSObject* obj =[[cls alloc] init];
                                obj.mjClass =[[cls alloc] init];
                                for (NSDictionary *d in content[key]) {
                                    [obj updateNewDataBaseWithDic:d andLimitType:@{arr.lastObject:[content valueForKey:key]}];
                                }
                                
                            }
                    }
                    }
                   else if (content[key]) {
                        [contentArr addObject:[NSString stringWithFormat:@"[%@]='%@'",key,content[key]]];
                    }
                   
                }
                if (contentArr.count>0) {
                [dataBaseTool setDataBaseWithSQLTxt:^NSString *{
               
                    NSMutableArray *keyArr = [NSMutableArray new];
                    for (NSString *key in type) {
                        [keyArr addObject:[NSString stringWithFormat:@"[%@] = '%@'",key,type[key]]];
                    }
                    NSString *updateCode=[NSString stringWithFormat:@"update %@  set  %@  where %@",  NSStringFromClass([self.mjClass class]),[contentArr componentsJoinedByString:@" ,"],keyArr.count>0?[keyArr componentsJoinedByString:@" and "]:@"1=1"];
                    return updateCode;
               
                return nil;
            } andFail:^(NSString * _Nonnull errorDes) {
                WJCLog(@"💔💔数据库插入数据报错:%@💔💔",errorDes);
            }];
                }
            }
        }else{
            [self insertNewDataBaseWithDic:content];
        }
    }];
    }
}
-(void)getNewDataBaseWithLimitType:(NSDictionary *)type andGetSub:(BOOL)getSub andOnlyValue:(BOOL)onlyValue andsuccess:(void(^)(id))success{
    [dataBaseTool getDataBaseWithSQLTxt:^NSString *{
        NSMutableArray *keyArr = [NSMutableArray new];
        for (NSString *key in type) {
            [keyArr addObject:[NSString stringWithFormat:@"[%@] = '%@'",key,type[key]]];
        }
        return [NSString stringWithFormat:@"select * from %@ where %@",NSStringFromClass([self.mjClass class]),keyArr.count>0?[keyArr componentsJoinedByString:@" and "]:@"1=1"];
    }andSuccess:^(NSArray * _Nonnull obj) {
        NSArray *property = [self getAllPropertNameWithClass:[self.mjClass class] returnClass:NO];
        for (NSDictionary *dic  in obj) {
            if (getSub) {
                NSDictionary *replace = [[self.mjClass class] wjc_localDataBaseUnion];
                
                for (NSString *key in replace) {
                    if ([property containsObject:key]) {
                        NSString *className = [self getKVTypeValueWithProperty:key];
                        NSArray *arr = [replace[key] componentsSeparatedByString:@"."];
                        if([className isEqual:@"NSMutableArray"]||[className isEqual:@"NSArray"]){
                            if ([[self.mjClass class] respondsToSelector:NSSelectorFromString(@"mj_objectClassInArray")]) {
                                if ([[self.mjClass class] mj_objectClassInArray][key]&&arr.count>0) {
                                    Class cls =[[[self.mjClass class] mj_objectClassInArray][key] isKindOfClass:[NSString class]]?NSClassFromString([[self.mjClass class] mj_objectClassInArray][key]):[[self.mjClass class] mj_objectClassInArray][key];
                                    NSObject* obj =[[cls alloc] init];
                                    obj.mjClass =[[cls alloc] init];
                                    
                                    [obj getNewDataBaseWithLimitType:@{arr.lastObject:[dic valueForKey:key]} andGetSub:getSub andOnlyValue:NO andsuccess:^(NSArray * _Nonnull object) {
                                        [dic setValue:object forKey:key];
                                    }];
                                }
                        }
                        }else if(className.length>1&&![className isEqual:@"NSMutableString"]&&![className isEqual:@"NSString"]&&![className isEqual:@"NSNumber"]&&![type isEqual:@"NSDictionary"]
                               &&![type isEqual:@"NSMutableDictionary"]&&arr.count>0){
                            NSObject* obj =[[NSClassFromString(className) alloc] init];
                            obj.mjClass =[[NSClassFromString(className) alloc] init];
                            [obj getNewDataBaseWithLimitType:@{arr.lastObject:[dic valueForKey:key]} andGetSub:getSub andOnlyValue:YES andsuccess:^(NSArray * _Nonnull object) {
                                [dic setValue:object forKey:key];
                            }];
                        }
                }
            }
        }
        }
        if (!onlyValue) {
            success([[self.mjClass class] mj_objectArrayWithKeyValuesArray:obj[0]]);//字典转模型
        } else {
            success([[self.mjClass class] mj_objectArrayWithKeyValuesArray:[NSDictionary changeType:obj]]);//字典数组转模型数组
        }
    } andFail:^(NSString * _Nonnull errorDes) {
        WJCLog(@"💔💔数据库查找数据报错:%@💔💔",errorDes);
    }];
}
@end
